#pragma once
#include <stdio.h>
#include <signal.h>
#include <atomic>
#include <string>
#include <thread>
#include <iostream>
#include <vector>
#include <mutex>
#include <queue>
#include <opencv2/opencv.hpp>

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libavutil/timestamp.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/audio_fifo.h>
#include <libavutil/avassert.h>
#include <libavutil/avstring.h>
#include <libavutil/dict.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}
#include "base_puller.h"
#include "base_util/math_compute.h"
#include "yuv_to_rgb.hpp"
#include "decoder_manager.h"

namespace stream {

class CUStreamPuller: public BasePuller
{
public:
  CUStreamPuller(BaseDecoderManger* decode_mnger, StreamPullerInfo* sifo, LogInfo* log_info);
  ~CUStreamPuller();

public:
  int init_params();
  int start_pull();
  int stop_pull();
  int get_frame(stream::ImageBlob& buffer);


private:

  void release_ffmpeg();
  int yuv2rgb_cuda(int input_width, int input_height, YUVHostImage *yuvhost, int output_width, int output_height, cv::Mat& img);

public: 


private:
  CUDecoderManger* decode_mng;

  std::mutex queue_lock;
  std::queue<stream::ImageBlob> queue_data;

  AVFormatContext *ifmt_ctx = nullptr;
  AVDictionary *optionsDict = nullptr;
  AVStream *pVst = nullptr;
  AVCodecContext *pVideoCodecCtx = nullptr;
  AVCodec *pVideoCodec = nullptr;
  AVFrame *pFrame = nullptr;
  int video_st_index = -1;
  int audio_st_index = -1;
  float cur_fps;

  // init module
  // void *display = nullptr;
  // void *vps = nullptr;

  std::string rtsp_main;
  std::vector<unsigned char> bgr_host_buffer;
  int input_batch;
  YUVGPUImage* input_gpu;
  RGBGPUImage* output_gpu;

};


}   // namespace camera
